﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using ControlzEx.Theming;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Threading;
using System.Drawing;
using System.Windows.Media.Animation;

namespace WpfBeyond
{
    /// <summary>
    /// WindowBc.xaml 的交互逻辑
    /// </summary>
    public partial class WindowDevice : MetroWindow
    {
        private Device device = null;

        List<TaskInfo> tasklist = null;

        //private delegate void InvokeHandler();//使用代理让主线程去处理控件数据

        private DispatcherTimer readDataTimer = null;

        public WindowDevice(Device d)
        {
            InitializeComponent();

            Reback_type_list reback_type_list = new Reback_type_list(cmb_reback_type);

            device = d;

            //载入后，初始化参数
            lbl_serialNo.Content = device.serialNo;
            txt_sourceCode.Text = device.Resource_code;
            //lbl_ip.Content = "IP地址:" + d.ipaddr;
            txt_ip.Text = device.Local_ip;
            txt_mask.Text = device.Local_mask;
            txt_gw.Text = device.Local_gw;

            txt_addr.Text = device.Addr;
            cmb_reback_type.SelectedIndex = device.reback_type - 1;
            txt_reback.Text = device.reback_param;

            lbl_error.Content = device.errCode;
            lbl_devType.Content = device.device_type;

            lbl_status.Content = device.StrStatus;
            tbx.Text = device.volume.ToString();

            lbl_hardware.Content = device.Hardware;
            lbl_software.Content = device.Software;

            grid_task.ItemsSource = device.tasklist;

            if (readDataTimer == null)
            {
                readDataTimer = new DispatcherTimer();//定时器 ;
                readDataTimer.Tick += new EventHandler(timeCycle);
                readDataTimer.Interval = new TimeSpan(0, 0, 0, 1);
            }

            readDataTimer.Start();
                        
        }

        /// <summary>
        /// 设置控件的【大小、背景】动画效果，
        /// 高度、宽度默认当前大小，背景默认White~LightGreen
        /// </summary>
        /// <param name="control">要设置动画的控件</param>
        /// <Author> frd 2011-9-8</Author>
        public static void SetColorAnimation(object control)
        {
            Type type = control.GetType();

            SolidColorBrush myBrush = new SolidColorBrush();

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.LightGreen;
            myColorAnimation.To = Colors.White;
            //myColorAnimation.To = ((SolidColorBrush)newBorder.Background).Color;
            myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(2));
            myColorAnimation.AutoReverse = false;

            switch (type.Name)
            {
                case "TextBox":
                    {
                        TextBox newBorder = (TextBox)control;

                        #region 背景颜色动画                                               
                        myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation, HandoffBehavior.Compose);
                        newBorder.Background = myBrush;
                        #endregion
                    }
                    break;

                case "Label":
                    {
                        Label newBorder = (Label)control;

                        #region 背景颜色动画                                                      
                        myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation, HandoffBehavior.Compose);
                        newBorder.Background = myBrush;
                        #endregion
                    }
                    break;

                default:
                    break;
            }
        }

        public void timeCycle(object sender, EventArgs e)
        {
            txt_adatime.Text = DateTime.Now.ToString();

            lock (device.lock_user)
            {
                for (int i = device.ReflashTagList.Count - 1; i >= 0; i--)
                {
                    if (device.ReflashTagList[i] == 0x1)//音量
                    {
                        tbx.Text = device.volume.ToString();
                        SetColorAnimation(tbx);
                    }
                    else if (device.ReflashTagList[i] == 0x2)
                    {
                        txt_ip.Text = device.Local_ip;
                        SetColorAnimation(txt_ip);
                        txt_mask.Text = device.Local_mask;
                        SetColorAnimation(txt_mask);
                        txt_gw.Text = device.Local_gw;
                        SetColorAnimation(txt_gw);
                    }
                    else if (device.ReflashTagList[i] == 0x3)
                    {
                        cmb_reback_type.SelectedIndex = device.reback_type - 1;
                        txt_reback.Text = device.reback_param;
                        SetColorAnimation(txt_reback);
                    }
                    else if (device.ReflashTagList[i] == 0x4)
                    {
                        txt_sourceCode.Text = device.Resource_code;
                        SetColorAnimation(txt_sourceCode);
                    }
                    else if (device.ReflashTagList[i] == 0x5)
                    {
                        lbl_serialNo.Content = device.serialNo;
                        SetColorAnimation(lbl_serialNo);
                    }
                    else if (device.ReflashTagList[i] == 0x6)
                    {
                        lbl_status.Content = device.StrStatus;
                        SetColorAnimation(lbl_status);
                    }
                    else if (device.ReflashTagList[i] == 0x7)//故障代码
                    {
                        lbl_error.Content = device.errCode.ToString();
                        SetColorAnimation(lbl_error);
                    }
                    else if (device.ReflashTagList[i] == 0x8)
                    {
                        lbl_devType.Content = device.device_type;
                        SetColorAnimation(lbl_devType);
                    }
                    else if (device.ReflashTagList[i] == 0x9)
                    {
                        lbl_hardware.Content = device.Hardware;
                        SetColorAnimation(lbl_hardware);
                    }
                    else if (device.ReflashTagList[i] == 0xA)
                    {
                        lbl_software.Content = device.Software;
                        SetColorAnimation(lbl_software);
                    }

                    device.ReflashTagList.RemoveAt(i);
                }
            }

        }

        private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
        {
            ToggleSwitch toggleSwitch = sender as ToggleSwitch;
            if (toggleSwitch != null)
            {
                if (toggleSwitch.IsOn == true)
                {

                }
                else
                {

                }
            }
        }

        private void File_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog();
            if (op.ShowDialog() == true)
            {
                string Target = op.FileName;
            }
        }

        private async void Bc_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;

            if (btn == null) return;

            if (device.socket == null)
            {
                await this.ShowMessageAsync("提示", "设备未上线！");
                return;
            }

            string ebmid = btn.Tag.ToString();//获取需要停止的TASK 的EBMID

            IpPacket bc = new IpPacket(0x2);

            try
            {
                //TaskInfo t = TaskFactory.GetTaskInfo(ebmid);
                TaskInfo t = device.GetTaskInfo(ebmid);
                Array.Copy(Common.STR2BCD(ebmid), bc.body.p_stop.ebmid, 18);
                bc.encode();
                device.socket.Send(bc.data, bc.data_len, SocketFlags.None);
                device.tasklist.Remove(t);

                await this.ShowMessageAsync("提示", "停止广播成功");

                grid_task.ItemsSource = null;
                grid_task.ItemsSource = device.tasklist;
            }
            catch (Exception ex)
            {
                LogHelp.Error(ex.ToString());
            }

        }

        private void Event_GetData(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Button btn = sender as Button;

            if( device.socket == null)
            {
                this.ShowMessageAsync("提示", "设备未上线！");
                return;
            }

            IpPacket packet = new IpPacket(0x11);//查询数据包

            switch (btn.Name)
            {
                case "btn_get_sourceCode":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x4);
                    break;
                case "btn_get_ip":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x2);
                    break;
                case "btn_get_status":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x6);
                    break;
                case "btn_get_volume":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x1);
                    break;
                case "btn_get_reback":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x3);
                    break;
                case "btn_get_error":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x7);
                    break;
                case "btn_get_devType":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x8);
                    break;
                case "btn_get_hardware":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0x9);
                    break;
                case "btn_get_software":
                    packet.body.p_query.param_num++;
                    packet.body.p_query.param_tag_list.Add(0xA);
                    break;
                case "btn_get_all":
                    packet.body.p_query.param_num = 10;
                    for (Byte i = 1; i <= 10; i++)
                    {
                        packet.body.p_query.param_tag_list.Add(i);
                    }
                    break;
                default:
                    break;
            }

            packet.encode();
            device.socket.Send(packet.data, packet.data_len, SocketFlags.None);

            sb.Remove(0, sb.Length);
            for (int i = 0; i < packet.data_len; i++)
            {
                sb.Append(packet.data[i].ToString("X2"));
            }
            LogHelp.Info("SEND [" + btn.Name + "] [" + device.socket.RemoteEndPoint.ToString() + "] : " + sb.ToString());

        }

        private void packeted_setData(IpPacket packet, byte Tag)
        {
            if (device.socket == null)
            {
                this.ShowMessageAsync("提示", "设备未上线！");
                return;
            }

            param_info param = new param_info();
            switch (Tag)
            {
                case 0x1:
                    packet.body.p_set.param_num++;

                    param.Tag = 0x1;
                    param.len = 1;
                    param.content = new byte[1];
                    param.content[0] = Convert.ToByte(tbx.Text);

                    packet.body.p_set.param_list.Add(param);
                    break;
                case 0x2:
                    packet.body.p_set.param_num++;

                    param.Tag = 0x2;
                    param.len = 12;

                    byte[] ip = Common.IP2BCD(txt_ip.Text);
                    byte[] mask = Common.IP2BCD(txt_mask.Text);
                    byte[] gw = Common.IP2BCD(txt_gw.Text);

                    param.content = new byte[12];

                    Array.Copy(ip, 0, param.content, 0, 4);
                    Array.Copy(mask, 0, param.content, 4, 4);
                    Array.Copy(gw, 0, param.content, 8, 4);

                    packet.body.p_set.param_list.Add(param);
                    break;
                case 0x3:
                    packet.body.p_set.param_num++;

                    param.Tag = 0x3;

                    byte reback_type = (byte)(cmb_reback_type.SelectedIndex + 1);
                    byte[] reback_param;

                    if (reback_type == 1)//IP加端口
                    {
                        string[] ip_param = txt_reback.Text.Split(":");
                        if (ip_param.Length != 2) return;

                        param.content = new byte[7];
                        param.content[0] = reback_type;

                        reback_param = Common.IP2BCD(ip_param[0]);
                        Array.Copy(reback_param, 0, param.content, 1, 4);

                        ushort port = Convert.ToUInt16(ip_param[1]);
                        byte[] bport = new byte[2];
                        bport[0] = (byte)((port >> 8) & 0xFF);
                        bport[1] = (byte)((port) & 0xFF);
                        Array.Copy(bport, 0, param.content, 5, 2);

                        param.len = 7;
                    }
                    else if (reback_type == 2)//域名
                    {
                        string[] ip_param = txt_reback.Text.Split(":");
                        if (ip_param.Length != 2) return;

                        reback_param = Encoding.UTF8.GetBytes(ip_param[0]);

                        param.content = new byte[4 + reback_param.Length];
                        param.content[0] = reback_type;

                        param.content[1] = (byte)reback_param.Length;
                        Array.Copy(reback_param, 0, param.content, 2, reback_param.Length);

                        ushort port = Convert.ToUInt16(ip_param[1]);
                        byte[] bport = new byte[2];
                        bport[0] = (byte)((port >> 8) & 0xFF);
                        bport[1] = (byte)((port) & 0xFF);
                        Array.Copy(bport, 0, param.content, 2 + reback_param.Length, 2);

                        param.len = (byte)(4 + reback_param.Length);
                    }
                    else if (reback_type == 3)//手机号
                    {
                        reback_param = Encoding.UTF8.GetBytes(txt_reback.Text);
                        param.content = new byte[1 + reback_param.Length];
                        param.content[0] = (byte)reback_param.Length;
                        Array.Copy(reback_param, 0, param.content, 1, reback_param.Length);
                        param.len = (byte)(1 + reback_param.Length);
                    }

                    packet.body.p_set.param_list.Add(param);
                    break;
                case 0x4:

                    packet.body.p_set.param_num++;
                    param.Tag = 0x4;
                    param.len = 19;
                    param.content = new byte[19];
                    //0x04：物理地址长度（1 字节） +物理地址（n 字节）+终端资源编码（n 字节）
                    param.content[0] = 6;
                    Array.Copy(Common.STR2BCD(device.SerialNo), 0, param.content, 1, 6);
                    Array.Copy(Common.STR2BCD(txt_sourceCode.Text.ToString()), 0, param.content, 7, 12);

                    packet.body.p_set.param_list.Add(param);
                    break;
                case 0x5:

                    packet.body.p_set.param_num++;
                    param.Tag = 0x5;
                    param.len = 1;
                    param.content = new byte[1];
                    //1 个字节的开关标识，0x01 表示关闭终端功放， 0x02 表示开启终端功放                    
                    if (tog_apa.IsOn == true)
                    {
                        param.content[0] = 0x2;
                    }
                    else
                    {
                        param.content[0] = 0x1;
                    }
                    packet.body.p_set.param_list.Add(param);
                    break;
                case 0x6:
                    packet.body.p_set.param_num++;

                    param.Tag = 0x6;

                    param.len = 4;//UTC 4字节
                    param.content = new byte[4];
                    double intResult = 0;
                    int tSeconds = 0;

                    intResult = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
                    tSeconds = (int)intResult;

                    byte[] utc = new byte[4];
                    utc[0] = (byte)((tSeconds >> 24) & 0xFF);
                    utc[1] = (byte)((tSeconds >> 16) & 0xFF);
                    utc[2] = (byte)((tSeconds >> 8) & 0xFF);
                    utc[3] = (byte)(tSeconds & 0xFF);

                    Array.Copy(utc, 0, param.content, 0, 4);

                    packet.body.p_set.param_list.Add(param);
                    break;
                default:
                    break;
            }
        }

        private void Event_SetData(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();

            if (device == null)
            {
                this.ShowMessageAsync("提示", "设备不存在！");
                return;
            }

            if (device.socket == null)
            {
                this.ShowMessageAsync("提示", "设备未上线！");
                return;
            }

            IpPacket packet = new IpPacket(0x12);//设置数据包
            //设置目标资源编码
            packet.body.dst_num = 1;
            packet.body.dst_obj = new byte[12];
            Array.Copy(Common.STR2BCD(device.Resource_code.ToString()), 0, packet.body.dst_obj, 0, 12);

            if (sender.GetType().Name == "ToggleSwitch")
            {
                ToggleSwitch toggle = sender as ToggleSwitch;
                packeted_setData(packet, 0x5);
            }            
            else
            {
                Button btn = sender as Button;

                switch (btn.Name)
                {
                    case "btn_set_addr":
                        device.Addr = txt_addr.Text.Trim();
                        return;

                    case "btn_set_sourceCode":
                        packeted_setData(packet, 0x4);
                        break;
                    case "btn_set_ip":
                        packeted_setData(packet, 0x2);
                        break;
                    case "btn_set_volume":
                        packeted_setData(packet, 0x1);
                        break;
                    case "btn_set_reback":
                        packeted_setData(packet, 0x3);
                        break;
                    case "tog_apa":
                        packeted_setData(packet, 0x5);
                        break;
                    case "btn_adatime":
                        packeted_setData(packet, 0x6);
                        break;
                    case "btn_set_all":
                        for (byte i = 1; i <= 6; i++)
                        {
                            packeted_setData(packet, i);
                        }
                        break;
                    default:
                        break;
                }
            }

            packet.encode();
            device.socket.Send(packet.data, packet.data_len, SocketFlags.None);

            sb.Remove(0, sb.Length);
            for (int i = 0; i < packet.data_len; i++)
            {
                sb.Append(packet.data[i].ToString("X2"));
            }
            LogHelp.Info("SEND [" + device.socket.RemoteEndPoint.ToString() + "] : " + sb.ToString());

        }

        private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            readDataTimer.Stop();
        }

        private void BtnTaskDetail_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;

            string ebmid = btn.Tag.ToString();

            TaskInfo t = TaskFactory.GetTaskInfo(ebmid);
            if (t == null)
            {
                Common.ShowMessage("提示", "任务信息错误！");
                return;
            }
            WindowTaskDetail w = new WindowTaskDetail(t);
            w.Show();
        }
    }
}
